package evolution;
import java.util.Random;

/*
 * Created on 14 nov. 2007
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */

/**
 * @author nancel
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */

public abstract class Algo1p1ES{

	int dim;
	int range;
	
	double[] best;
	double[] child;
	
	double sigma;
	
	GaussianRandom generator = new GaussianRandom();
	
	Random random = new Random();
	
	int N ;
	
	public Algo1p1ES(int dim, int range, int n){
		
		this.dim = dim;
		this.range = range;
		this.N = n;
		
	}
	
	void init(){
		best = new double[dim];
		child = new double[dim];
		for (int i = 0; i < dim; i++){
			best[i] = random.nextDouble()*range - range/2;
		}
		
	}
	
	double[] mutate(double[] vect, double fact){
		
		double[] res = new double[dim];
		
		for (int i = 0; i < dim; i++){
			Random r = new Random();
			res[i] = vect[i] + fact * (r.nextGaussian());
			// System.out.println("###   " + (res[i] - vect[i]));
		}
		
		return res;
		
	}
	
//	double fitness(double[] v){
//		
//		double res = 0;
//		
//		for (int i = 0; i < DIM; i++){
//			res += v[i]*v[i];
//		}
//		
//		return res;
//		
//	}
	
//	double fitness(double[] v, boolean last){
//		
//		double error = 0;
//		
//		Perceptator perceptron = new Perceptator(2, 16, 1, v);
//		
//		
//		for (int i = 0; i < entrees_test.length; i++)
//			error += Math.pow(sorties_attendues[i] - perceptron.run(entrees_test[i], last)[0], 2);
//		
//		return error / sorties_attendues.length;
//		
//	}
	
	abstract double fitness(double[] v);
	
	double[] flatten(double[][] pec, double[][] pcs){
		
		int taille = 0, indice = 0;
		for (int i = 0; i < pec.length; i++)
			taille += pec[i].length;
		
		for (int i = 0; i < pcs.length; i++)
			taille += pcs[i].length;
		
		double[] res = new double[taille];
		
		for (int i = 0; i < pec.length; i++)
			for (int j = 0; j < pec[i].length; j++){
				res[indice] = pec[i][j];
				indice++;
			}
		
		for (int i = 0; i < pcs.length; i++)
			for (int j = 0; j < pcs[i].length; j++){
				res[indice] = pcs[i][j];
				indice++;
			}
		
		return res;
		
	}
	
	
	void run(boolean adapt){
		
		init();
		
		if(!adapt)
			sigma = range / 3;
		
		else
			sigma = 0.000001;
		
		int every = 1;
		StringBuffer sb = new StringBuffer();
		
		System.out.println("Debut");
		
		for(int i = 0; i < N; i++){
			
			// System.out.println("\nEtape " + i + ", sigma = " + sigma);
			
			child = mutate(best, sigma);
			
			// System.out.println("\nchild " + fitness(child));
			// System.out.println("\nbest " + fitness(best));
			
			if (fitness(child) <= fitness(best)){
				
				best = child;
				// System.out.println("best = child");
				
				if (adapt)
					sigma *= 2;
				
			}
			else{
				
				if (adapt)
					sigma *= Math.pow(2.0, -0.25);
				
			}
		
		}
		

		 System.out.println("Best : " + fitness(best));
		 // System.out.println(sb);

	
	}

}

